//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright 1995-2000 Microsoft Corporation.  
//
// @doc 
//
// @module CTable Header Module | This module contains header information for CTable
//
// @normal (C) Copyright 1995-1998 Microsoft Corporation.  All Rights Reserved.
//
// @comm
// Special Notes...:	(OPTIONAL NOTES FOR SPECIAL CIRCUMSTANCES)
//
// <nl><nl>
// Revision History:<nl>
//	
//	[00] MM-DD-YY	EMAIL_NAME	ACTION PERFORMED... <nl>
//	[01] 10-05-95	Microsoft	Created <nl>
//	[02] 12-01-96	Microsoft	Updated for release <nl>
//
// @head3 CTable Elements|
//
// @subindex CTable|
//
//---------------------------------------------------------------------------

#ifndef _CTable_HPP_
#define _CTable_HPP_

//-----------------------------------------------------------------------------
// @comm #pragma warning (disable: 4251) - This warning is generated by having
// CLists as member variables in a class that is exposed through
// a dll interface. This is simply a warning. The CList member variables
// are not exposed even if they are public data members. There have to be Get/Set
// functions that handle these member variables.
//	
//-----------------------------------------------------------------------------
#pragma warning (disable :4251)

/////////////////////////////////////////////////////////////////////
// Includes
//
/////////////////////////////////////////////////////////////////////
#include "CCol.hpp"
#include "CTree.hpp"
#include "List.h"

#define	READ_DBPROP_COL_AUTOINCREMENT	1
#define READ_DBPROP_COL_DEFAULT			2
#define READ_DBPROP_COL_FIXEDLENGTH		4	
#define READ_DBPROP_COL_NULLABLE		8
#define READ_DBPROP_COL_UNIQUE			16
#define READ_COL_CLSID					32


const ULONG	COL_NOT_COND		= 0x1;
const ULONG	COL_COND_NULL		= 0x2;
const ULONG	COL_COND_DEFAULT	= 0x4;
const ULONG	COL_COND_UNIQUE		= 0x8;
const ULONG COL_COND_UPDATEABLE	= 0x10;
const ULONG	COL_COND_AUTOINC	= 0x20;
const ULONG COL_COND_NOTNULL		= COL_COND_NULL			|	COL_NOT_COND;
const ULONG	COL_COND_NOTDEFAULT		= COL_COND_DEFAULT		|	COL_NOT_COND;
const ULONG	COL_COND_NOTUNIQUE		= COL_COND_UNIQUE		|	COL_NOT_COND;
const ULONG	COL_COND_NOTUPDATEABLE	= COL_COND_UPDATEABLE	|	COL_NOT_COND;
const ULONG COL_COND_NOTAUTOINC		= COL_COND_AUTOINC		|	COL_NOT_COND;


//--------------------------------------------------------------------
// @class A class used to generate internation strings based on the code
// page.

class CLocaleInfo
{
public:
	//Convstructors
	CLocaleInfo(LCID lcid);
	virtual ~CLocaleInfo();
	
	//String Creation Methods	
	virtual BOOL	MakeUnicodeIntlString(WCHAR* pwsz, INT len);
	virtual BOOL	MakeUnicodeIntlData(WCHAR* pwsz, INT len);
	virtual BOOL	MakeAnsiIntlString(CHAR* psz, INT len);
	virtual WCHAR	MakeUnicodeChar();
	virtual void	MakeAnsiChar(CHAR* pcLead, CHAR* pcTrail);
	virtual WCHAR*	MakeUnicodeInt(int val);
	
	//Localized Convervsion Methods
	virtual HRESULT	LocalizeString(WCHAR* pwszString, BSTR* pbstrLocalizedString);
	virtual HRESULT	LocalizeVariant(VARIANT* pVariant, VARIANT* pVarLocalized);

	//Interface
	virtual BOOL SetAnsiSeed(INT val);
	virtual BOOL SetUnicodeSeed(INT val);

protected:
	LCID			m_lcid;
	WCHAR*			m_wszUnicodeChars;
	UCHAR*			m_szAnsiChars;
	INT				m_cchUnicode;
	INT				m_cchAnsi;
	INT				m_seedUnicode;
	INT				m_seedAnsi;
	INT				m_nCharMaxWidth;
	WCHAR*			m_wszSurrogateChars;
};

//-----------------------------------------------------------------------------
// @class CTable | The class is responsible for creating, manipulating, 
// and deleting tables. The columns of the tables are actually CCol objects.
//	
// <nl><nl>
// Caveat 1: Important pointers<nl>
// The constructor has to have the DataSource Object and Session Object
// passed to it or the class will not work. However, the IMalloc
// pointer is created inside the constructor so the class can 
// manage its own memory. This IMalloc pointer is passed down 
// to the CCol class's constructor, so the CCol and CTable objects
// are meant to be used together. <nl>
//	
// <nl>
// Caveat 2: SQL Statments<nl>
// The BuildCommand/Execute commands and Select command have similar 
// functionality. But for insert/update/delete, the ExecuteCommand
// cannot be used. The CreateSQLStmt/BuildCommand/ExecuteCommand
// functions should be reviewed before use. Each has several uses.<nl>
//	
// <nl>
// Caveat 3: The following functions are not implemented currently: <nl>
// DoesIndexExist()<nl>
// SetExistingTable()<nl>
// SetFromIColumnsInfoGetColumnInfo()<nl>
// SetFromColumnsRowset()<nl>
// SetTableColumnInfo()<nl>
//	
// <nl>
// Caveat 4:Array numbers<nl>
// CCol objects are actually stored in the CTable in the MFC class of
// CList,which is 0 based. <nl>
// Columns in the base table are 1 based unless there is a bookmark.
// Then the bookmark is the 0th element.<nl>
// Rows in the base table and CTable object are 1 based.<nl>
//
//-----------------------------------------------------------------------------
class CTable : public CSchema
{
	// @access Private
	private:	 

	// @cmember Name of view over this table. <nl>
	WCHAR * m_pwszViewName;

	// @cmember Structure containing table name, used for ITableDefinition. <nl>
	DBID	m_TableID;

	// IDBInfo (used Literals)
	ULONG			m_cLiteralInfo;
	DBLITERALINFO*	m_rgLiteralInfo;
	WCHAR*			m_pwszLiteralInfoBuffer;

	// @cmember Name of index on this table. <nl>
	WCHAR * m_pwszIndexName;

	// @cmember Test case module name. <nl>
	WCHAR *	m_pwszModuleName;

	// @cmember Total number of rows in CTable object. <nl>
	DBCOUNTITEM 	m_ulRows; 
	
	// @cmember Next row to insert, used in Insert ONLY. <nl>
	DBCOUNTITEM 	m_ulNextRow; 

	// @cmember Indicates what SQL Support the Provider has.
	LONG_PTR	m_lSQLSupport;
	
	// @cmember DataSource interface
	IDBInitialize* m_pIDBInitialize;	

	// @cmember Session interfaces
	IOpenRowset* m_pIOpenRowset;	
	IDBCreateCommand* m_pIDBCreateCommand;	

	// @cmember Error object used to verify OLE DB calls. <nl>
	CError *	m_pError;

	// @cmember Outer Unknown (controlling unknown) for use with ITableDefinition::CreateTable <nl>
	IUnknown*	m_pUnkOuter;

	// @cmember REFIID in ITableDefinition::CreateTable <nl>
	IID*		m_riid;

	// @cmember Pointer to DBID returned by ITableDefinition::CreateTable <nl>
	DBID**		m_ppTableID;

	// @cmember Pointer to the rowset interface returned when creating a table <nl>
	IUnknown**	m_ppRowset;

	// @cmember Array of property sets used for ITableDefinition::CreateTable <nl>
	DBPROPSET	*m_rgPropertySets;

	// @cmember Number of elements in the array of properties <nl>
	ULONG		m_cPropertySets;

	// @cmember Array of column descriptors used for ITableDefinition::CreateTable <nl>
	DBCOLUMNDESC* m_rgColumnDesc;

	// @cmember Number of elements in the array of column descriptors <nl>
	DBORDINAL		m_cColumnDesc;

	// @cmember Whether to use a NULL Table ID in ITableDefinition::CreateTable <nl>
	BOOL		m_fInputTableID;

	// @cmember Whether to build a list of column desc for ITableDefinition::CreateTable <nl>
	BOOL		m_fBuildColumnDesc;
	
	// tell what props and supl info are available on col
	// @cmember Column Has Default Value
	BOOL		m_fHasAuto;

	// @cmember Column Has Default Value
	BOOL		m_fHasUnique;

	// @cmember Column Has Default Value
	BOOL		m_fHasCLSID;
	
	// @cmember Column Has Default Value
	BOOL		m_fHasDefault;      

	// @cmember Flag for available column properties (which properties of the column were got)
	ULONG	m_fColProps;

	// @cmember Flag if the Provider is ReadOnly
	ULONG	m_fProviderReadOnly;

	// @cmember ULONG for the Identifier Case
	ULONG_PTR	m_ulIdentifierCase;

	// @cmember Cached PROVIDER_TYPES schema info
	CSchema *	m_pSchemaCache;

	// @access Public
	public:	
	// @cmember Command object to use in this class. <nl>
	ICommand * m_pICommand;	

	// migrate to use this function instead of using public member m_pICommand
	virtual inline ICommand * get_ICommandPTR(void) { return m_pICommand;	};
	virtual inline void set_ICommandPTR( ICommand *pICommand) { m_pICommand = pICommand; };
	
	// @cmember Constructor. There is only one. <nl>
	CTable(
		IUnknown *		pSessionIUnknown,		// [IN] CreateCommand pointer from client 
		WCHAR *			pwszModuleName=NULL,	// [IN] Table name, optional (Default=NULL)
		ENULL			eNull=USENULLS			// [IN] Should nulls be used (Default=USENULLS)
	);	

	// @cmember Destructor. Gets rid of any memory. <nl>
	virtual ~CTable(void);

	// @cmember Builds an array used by ITableDefinition::CreateTable, <nl>
	// based on column info. <nl>
	HRESULT BuildColumnDescs(DBCOLUMNDESC** prgColumnDescs);	
	
	// @cmember Builds a DBCOLUMNDESC stru used by ITableDefinition::CreateTable, <nl>
	// and ITableDefinition::AddColumn based on column info. <nl>
	HRESULT BuildColumnDesc(DBCOLUMNDESC *pColumnDesc, CCol& CurCol);	
	
	// @cmember PrintTable. Prints CCol Info in debug window ONLY. <nl>
	void PrintCColInfo();

	// @cmember Reset the pointer to IDBCreateCommand inside CTable. <nl>
	// This function should only be called within the same Data Source object. <nl>
	// The intention of this method is for CTransaction class so that when <nl>
	// ExecuteCommand is called, a new pIDBCreateCommand is used for the new <nl>
	// transacion.	<nl>
	HRESULT	ResetCreateCommand(
		IDBCreateCommand	*pIDBCreateCommand	// [IN] IDBCreateCommand pointer
	);

	// @cmember Returns if Non null columns can be created on the database.
	BOOL IsNonNullColumnsAllowed();

	// @cmember Returns the SQLSupport of a Provider.
	void ProviderSQLSupport();

	// @cmember Creates table of all types found in Data Source #1. Default behavior <nl>
	// creates a table with an autogenerated table name. The table has no rows. The <nl>
	// index is on the first column. <nl>
	HRESULT CreateTable(	
		DBCOUNTITEM	ulRowCount, 			// [IN] Number of rows to generate, 1 based
		DBORDINAL	ulIndex=1,				// [IN] Column that has index, 1 based (Default=1)
		WCHAR *		pwszTableName=NULL,		// [IN] TableName,if NULL will be created internally (Default=NULL)
		EVALUE 		eValue=PRIMARY,			// [IN] Initial or second value of data to insert (Default=PRIMARY)
		BOOL		fFirstUpdateable=FALSE	// [IN] TRUE means first column will not be autoinc (Default=FALSE)
	);

	// @cmember Creates table based on list of provider types #2. Default behavior <nl>
	// creates a table with an autogenerated table name. The table has no rows. The <nl>
	// index is on the first column. <nl>
	// Please note that the private library will NOT <nl>
	// arrange your columns. The order you pass them in is the order the table will <nl>
	// be created. If any column you pass in can't be created or the index can't <nl>
	// be created on the column specified, the table creation will fail. <nl>
	HRESULT CreateTable(	
		CList <DBTYPE,DBTYPE>& rDBTypesList,	// [IN] Types of columns
		DBCOUNTITEM	ulRowCount,					// [IN] Number of rows to generate, 1 based
		DBORDINAL	ulIndex=1,					// [IN] Column that has index (Default=1)
		WCHAR * 	pwszTableName=NULL,			// [IN] TableName,if NULL will be created internally  (Default=NULL)	
		EVALUE 		eValue=PRIMARY,				// [IN] Initial or second value of data to insert (Default=PRIMARY)
		BOOL		fFirstUpdateable=FALSE		// [IN] TRUE means first column will not be autoinc (Default=FALSE)
	);

	// @cmember Creates table based on list of native types #3.Default behavior <nl>
	// creates a table with an autogenerated table name. The table has no rows. The <nl>
	// index is on the first column. <nl>
	// Please note that the private library will NOT <nl>
	// arrange your columns. The order you pass them in is the order the table will <nl>
	// be created. If any column you pass in can't be created or the index can't <nl>
	// be created on the column specified, the table creation will fail. <nl>
	HRESULT	CreateTable(	
		CList <WCHAR * ,WCHAR *>& rNativeTypesList,	// [IN] Types of columns
		DBCOUNTITEM	ulRowCount,						// [IN] Number of rows to generate 
		DBORDINAL	ulIndex=1,						// [IN] Column that has index (Default=1)
		WCHAR * 	pwszTableName=NULL,				// [IN] TableName,if NULL will be created internally (Default=NULL)
		EVALUE 		eValue=PRIMARY,					// [IN] Initial or second value of data (Default=PRIMARY)
		BOOL		fFirstUpdateable=FALSE			// [IN] TRUE means first column will not be autoinc (Default=FALSE)

	);

	// @cmember Creates Index on Table. Default behavior creates unique index <nl>
	// on column 1.	 <nl>
	// "create [unique] index index_name on table_name (column_name)" , uses <nl>
	// column ordinal number (m_ColNum). Index name is same as table name. Index <nl>
	// is unique if EINDEXTYPE is UNIQUE, else not unique. <nl>
	HRESULT	CreateIndex(
		DBORDINAL	ulColNum=1,			// [IN] Column number,first column should be numeric (Default=1)
		EINDEXTYPE 	eIndexType=UNIQUE,	// [IN] Constraint type (Default=UNIQUE)
		LPWSTR		pwszIndexName=NULL	// [IN] Index name to use, default NULL will use table name.
	);

	// @cmember Creates Index on Table. Default behavior creates unique index 
	// Used to create an index on one or more columns
	HRESULT CTable::CreateIndex(
		DBORDINAL*	rgulOrdinals,			// [IN] Array of ordinals
		DBORDINAL	cOrdinals,				// [IN] Count of ordinals
		EINDEXTYPE 	eIndexType=UNIQUE,		// [IN] Type of index (Default = UNIQUE)
		LPWSTR		pwszIndexName=NULL		// [IN] Index name to use, default NULL will use table name.
	);

	// @cmember Builds a select statement on table, executes if requested.
	// This function is an alternative to BuildComand and ExecuteCommand.
	// It would be used when you know which singular row you want returned.
	HRESULT	Select( 
		IUnknown*		pIUnkOuter,				// [IN]  Aggregate
		DBCOUNTITEM		ulRowNumber,			// [IN]  Row number to select
		REFIID 			riid,					// [IN]  Type of interface user wants back
		ULONG			cPropSets,				// [IN]	 Count of property sets.
		DBPROPSET*		rgPropSets,				// [IN]	 Array of DBPROPSET structures.
		DBROWCOUNT*		pcRowsAffected,			// [OUT] Pointer to memory in which to return the count
												//			of rows affected by a command that updates, deletes,
												//			or inserts rows.
		IUnknown **		ppIUnknown,				// [OUT] Interface pointer user wants back (Default=NULL)
		ICommand **		ppICommand=NULL			// [IN/OUT] If ppICommand == NULL, this function uses
													// its own command object and then frees it, caller does nothing.
													// <nl>
													// If *ppICommand is not null, this value is used as the
													// ICommand interface for all command operations in this function. 
													// Caller maintains responsiblity to release this interface.
													// <nl>
													// If *ppICommand is null, this function creates a new command object
													// and places the ICommand interface to this object in *ppICommand.
													// Caller assumes responsibility to release this interface.
	);								

	// @cmember Inserts a row into the table.  If commands are supported,
	// it builds insert SQL statement and executes if requested.
	// If commands are not supported, IRowsetNewRow is used to insert data, 
	// but only if fExecute = TRUE.
	// Default behavior is to insert the next row.<nl>
	// Inserts 1 row into the table. If ulRowNumber == 0 then ulRowNumber
	// == m_ulNextRow. Rownumbers start at 0 in the private library, regardless
	// of how they are treated in the Data Source. 
	// ppwszInsert should look like "Insert into table (col1,...) values (x, ...)".
	// Client must IMalloc->Free(pwszInsert) if not passed as NULL.
	// If pwszSelect == NULL, client doesn't want statement returned.
	HRESULT Insert(
		DBCOUNTITEM	ulRowNumber=0,	// [IN]  Row number to insert (Default = Next row)
		EVALUE 		eValue=PRIMARY,	// [IN]  Initial or second value of data (Default=PRIMARY)
		BOOL 		fExecute=TRUE,	// [IN]  True indicates execute statement (Default=TRUE)
		WCHAR ** 	pwszInsert=NULL,// [OUT] SQL statement generated.  NULL is returned in commands aren't supported (Default=NULL)
		BOOL		fNULL=FALSE,	// [IN]  TRUE indicates that NULL values will be inserted whenever possible
		DBCOUNTITEM	cRowsToInsert = 1
	);           

	// @cmember Inserts using IRowsetChange::InsertRow <nl>
	HRESULT Insert(			
		EVALUE 		eValue,				// [IN]  Initial or second value of data 
		DBCOUNTITEM	ulRowNumber,		// [IN]  Row number to insert
		DBCOUNTITEM	cRowsToInsert = 1	// [IN]  number of rows to insert			
	);     

	// @cmember Inserts a row into the table using commands with a literal insert statements.
	// the values specified by user.
	HRESULT InsertWithUserLiterals(	
	DBORDINAL cCols,				// [IN] number of values to insert	
	DBORDINAL *pulColOrdinals,	// [IN] array of column ordinals
	WCHAR	**pwszLiterals		// [IN] values to insert
	);
		
	// @cmember Inserts a row into the table with parameters.  This function will only
	// work when commands are supported.  it builds the sql statements and executes if
	// requested.
	// pwszInsert should look like "Insert into table (col1, ...) values (?, ...);
	HRESULT InsertWithParams(
		DBCOUNTITEM	ulRowNumber=0,		// [IN]  Row number to insert (Default = Next row)
		EVALUE 		eValue=PRIMARY,		// [IN]  Initial or second value of data (Default=PRIMARY)
		BOOL 		fExecute=TRUE,		// [IN]  True indicates execute statement (Default=TRUE)
		WCHAR ** 	pwszInsert=NULL,	// [OUT] SQL statement generated.  NULL is returned in commands aren't supported (Default=NULL)
		DBCOUNTITEM	cRowsToInsert = 1
	); 

	// @cmember Builds an update statement on table, executes if requested.
	// Default behavior is to delete the last row inserted.<nl>
	// Client must IMalloc->Free(pwszUpdate).
	// Updates 1 row in table. Client must have at least one column marked
	// or an error will occur. eValue is the type of MakeData data you are going to
	// update the column to (the end result).
	// If pwszSelect == NULL, client doesn't want statement returned.
	HRESULT	Update(	
		DBCOUNTITEM	ulRowNumber=0,		// [IN]  Row number to update (Default=last row inserted into table)
		EVALUE 		eValue=SECONDARY,	// [IN]  Kind of new value to set (Default=SECONDARY)
		BOOL 		fExecute=TRUE,		// [IN]  True indicates execute statement (Default=TRUE)
		WCHAR ** 	pwszUpdate=NULL,	// [OUT] SQL statement generated (Default=NULL)
		BOOL		fSameWhereValuesAsSet = FALSE,	// [IN]  Whether to look for same value in where clause which is used in
										//       set clause and thus basically perform an update which doesn't
										//       change anything for the given row.  (Default = FALSE, meaning
										//       the opposite of eValue will be used to generate the where clause,
										//       and thus the updated row will show a new value.)
		DBCOUNTITEM	ulWhereRowNumber=0	// [IN] if not 0 then update table set ulRowNumber where ulWhereRowNumber
	);								

	// @cmember Builds a delete statement on table, executes if requested.
	// Default behavior deletes all rows in table.<nl>
	// Client must IMalloc->Free(pwszSelect).
	// Deletes 1 row or all rows. If pstrSelect is NULL, client will not
	// be returned the sql text of the delete statement. eValue is the current
	// value of the data to be deleted.
	// If pwszSelect == NULL, client doesn't want statement returned.
	HRESULT	Delete( 
		DBCOUNTITEM	ulRowNumber=ALLROWS,// [IN]  Row number to update (Default=ALLROWS)
		EVALUE 		eValue=PRIMARY,		// [IN]  Initial or second value of data (Default=PRIMARY)
		BOOL 		fExecute=TRUE,	  	// [IN]  True indicates execute statement (Default=TRUE)
		WCHAR ** 	pwszSelect=NULL		// [OUT] SQL statement generated (Default=NULL)
	);								

	// @cmember Creates a SQL statement from one of the predefined statements 
	// and then executes that statement, Client must free any memory returned.
	// If the client doesn't pass in a Command pointer for this function to 
	// work from, the private library has one it will use.
	// Options include:<nl>
	// (1)If the statement is a join that requires a second table, the second
	// table name must be passed in. <nl>
	// (2)Not executing statement, this would be interested when you want 
	// other information returned such as the sql statement.<nl>
	// (3)Properties can be set and the errors associated with those properties
	// can be returned.	<nl>
	// (4) The following must be IMalloc->Freed if passed in as valid addresses:<nl>
	// ppwszStatement,prgColumns,prgPropertyErrors,prgpRowset.
	//	Client must release the following objects:	  <nl>
	//		- If pICommand is not null user must release this<nl>
	//	Client must free the following memory:<nl>
	//		- If prgPropertyErrors is not null user must free this<nl>
	//		- If pcRowset is zero then user must free prgpRowset<nl>
	//		- ppwszStatement<nl>
	//		- prgColumns<nl>
	//
	//	This function takes a mandatory SQL statement.<nl>
	HRESULT ExecuteCommand(
		EQUERY				eSQLStmt,				// [IN]  SQL statement to create 
		REFIID				riid,					// [IN]  Interface pointer to return
		WCHAR * 			pwszTableName=NULL,		// [IN]  Second TableName
		WCHAR **			ppwszStatement=NULL,	// [OUT] SQL statement generated
		DBORDINAL *			pcColumns=NULL,			// [OUT] Count of columns
		DB_LORDINAL **		prgColumns=NULL,		// [OUT] Array of column numbers
		EEXECUTE			eExecute=EXECUTE_IFNOERROR,// [IN] TRUE = execute SQL Statement
		ULONG				cPropSets=0,			// [IN]  Count of property sets.
		DBPROPSET			rgPropSets[]=NULL,		// [IN]  Array of DBPROPSET structures.
		DBROWCOUNT *		pcRowsAffected=NULL,	// [OUT] Pointer to memory in which to return the count
													// of rows affected by a command that updates, deletes,
													// or inserts rows.
		IUnknown **			ppRowset=NULL,			// [IN/OUT] Pointer to the rowset pointer.
		ICommand **			ppICommand=NULL			// [IN/OUT] If ppICommand == NULL, this function uses
													// its own command object and then frees it, caller does nothing.
													// <nl>
													// If *ppICommand is not null, this value is used as the
													// ICommand interface for all command operations in this function. 
													// Caller maintains responsiblity to release this interface.
													// <nl>
													// If *ppICommand is null, this function creates a new command object
													// and places the ICommand interface to this object in *ppICommand.
													// Caller assumes responsibility to release this interface.
	);						


	// @cmember Creates a Rowset 
	HRESULT CreateRowset(
		EQUERY				eQuery,						// [IN]  Query to create 
		REFIID				riid,						// [IN]  Interface pointer to return
		ULONG				cPropSets=0,				// [IN]  Count of property sets.
		DBPROPSET*			rgPropSets = NULL,			// [IN]  Array of DBPROPSET structures.
		IUnknown **			ppRowset = NULL,			// [OUT] Pointer to the rowset pointer.
		DBID*				pTableID = NULL,			// {IN]  TableID if needed (IOpenRowset)
		DBORDINAL *			pcColumns = NULL,			// [OUT] Count of columns
		DB_LORDINAL **		prgColumns = NULL,			// [OUT] Array of column numbers
		ULONG				cRestrictions = 0,			// [IN] cRestrictions
		VARIANT*			rgRestrictions = NULL,		// [IN] rgRestrictions
		IOpenRowset*		pIOpenRowset = NULL			// [IN] pIOpenRowset
	);						

	// @cmember Sets properties on a command object and executes the sql statement
	// Client must release and/or free any object and/or memory returned;
	// If the client doesn't pass in a Command pointer for this function to 
	// work from, the private library has one it will use.
	// Options include:<nl>
	// (1)If the statement is a join that requires a second table, the second
	// table name must be passed in. <nl>
	// (2)Not executing statement, this would be interested when you want 
	// other information returned such as the sql statement.<nl>
	// (3)Properties can be set and the errors associated with those properties
	// can be returned.	<nl>
	// (4) Parameters can be set.<nl>
	// (5) The following must be IMalloc->Freed if passed in as valid addresses:<nl>
	// ppwszStatement,prgPropertyErrors,prgpRowset.<nl>
	// Client must release the following objects:<nl>
	//		- If pICommand is not null user must release this<nl>
	// Client must free the following memory:<nl>
	//		- If prgPropertyErrors is not null user must free this<nl>
	//		- If pcRowset is zero then user must free prgpRowset<nl>
	//
	// This function takes a mandatory SQL statement.
	// This function will create a command object, set any properties passed in,
	// set the SQL statement, and execute the statement if fExecute = TRUE;
	// The user has the option of setting parameters, retrieving the count of
	// rowsets, retrieving the array of rowsets, retrieving the interface pointer
	// specified in the REFIID, and retrieving the command object.
	HRESULT BuildCommand(
		LPCWSTR				pwszCommand,			// [IN]  SQL Statement to set
		REFIID				riid,					// [IN]  Interface pointer to return
		EEXECUTE eExecute = EXECUTE_IFNOERROR,		// [IN]  When to execute the SQL Statement
		ULONG				cPropSets=0,			// [IN]  Count of property sets.
		DBPROPSET 			rgPropSets[]=NULL,		// [IN]  Array of DBPROPSET structures.
		DBPARAMS *			pParams=NULL,			// [IN]  Parameters to pass to ::Execute
		DBROWCOUNT *		pcRowsAffected=NULL,	// [OUT] Pointer to memory in which to return the count
													// of rows affected by a command that updates, deletes,
													// or inserts rows.
		IUnknown **			ppRowset=NULL,			// [IN/OUT] Pointer to the rowset pointer.
		ICommand **			ppICommand=NULL,		// [IN/OUT] If ppICommand == NULL, this function uses
													// its own command object and then frees it, caller does nothing.
													// <nl>
													// If *ppICommand is not null, this value is used as the
													// ICommand interface for all command operations in this function. 
													// Caller maintains responsiblity to release this interface.
													// <nl>
													// If *ppICommand is null, this function creates a new command object
													// and places the ICommand interface to this object in *ppICommand.
													// Caller assumes responsibility to release this interface.
		IUnknown*				pIUnkOuter = NULL	// @parm [IN] Aggregate
	);
   
	// @cmember Creates a SQL statement from one of the predefined statements
	// Client must free ppwszStatement and prgColumns.
	// This function takes a one of the enum SQL Statements and creates the
	// SQL statement with the columns and the CTable.  The statement is then
	// passed back to the user along with an array of column numbers in the
	// order they will come back in the result set.
	HRESULT CreateSQLStmt(
		EQUERY			eSQLStmt,		// [IN]  SQL statement to create 
		WCHAR * 		pwszTableName,	// [IN]  Second TableName
		WCHAR **		ppwszStatement,	// [OUT] SQL statement generated
		DBORDINAL *		pcColumns=NULL,	// [OUT] Count of columns (Default = NULL)
		DB_LORDINAL **	prgColumns=NULL,// [OUT] Array of column numbers (Default = NULL)
		DBCOUNTITEM		ulRowNumber = 1,// [IN]  Row number to use
		CTable *		pTable2 = NULL,	// [IN]  Second table object to use
		DBORDINAL		iOrdinal = 0	// [IN]	 Col number to use, default 0 (all)
	);

	// @cmember Creates a list from the Ctable
	// Client must free ppwszList, prgColumns.
	// This function creates a list from the CTable.  The list
	// will be comma seperated.  This function also returns an array of
	// column numbers.
	HRESULT CreateList(
		ELIST_TYPE		eListType,		// @parm [IN] Type of list to create	
		LPWSTR *		ppwszList,		// @parm [OUT] List generated
		DBORDINAL *		pcColumns = NULL,		// @parm [IN/OUT] In:  Maximum number of columns that can be 
										// in the Column array. Ignored if *prgColumns==NULL.
										// Out:  Actual number of columns in finished array.									
		DB_LORDINAL **	pprgColumns = NULL,	// @parm [IN/OUT] Array of column numbers, memory is allocated for caller
										// if *pprgColumns == NULL, else it is assums the array is *pcColumns
										// allocated by caller to hold all column numbers and the first column
										// is a constant column such as 'ABC'.
		ECOLS_IN_LIST	eColsInList = ALL_COLS_IN_LIST,	// @parm [IN] Type of columns in list (Default = ALL_COLS_IN_LIST)
		ECOLUMNORDER	eColOrder = FORWARD,		// @parm [IN]  Column list order, default FORWARD
		EVALUE			eValue = PRIMARY,			// @parm [IN] Type of makedata (Default = PRIMARY)
		DBCOUNTITEM		ulRowNum = 1,		// @parm [IN] Row number to use for literals, default 1
		LPWSTR **		pprgColumnNames = NULL,	// @parm[OUT] Column names, if null are not returned, (Default = NULL)
										// Client must release each string and array of strings
		DBORDINAL *	prgColumns = NULL			// @parm [IN]   On input specifies desired columns,
										// over-riding eColsInList.  Default NULL.
	);

	
	// @cmember Creates a column list from the Ctable
	// Client must free ppwszColList, prgColumns.
	// This function creates a column list from the CTable.  The column list
	// will be comma seperated.  This function also returns an array of
	// column numbers.
	HRESULT CreateColList(
		ECOLUMNORDER	eColOrder,			// [IN]  Column list order, default FORWARD
		WCHAR **		ppwszColList,		// [OUT] Column list generated
		DBORDINAL *		pcColumns,			// [OUT] Count of columns
		DB_LORDINAL **	prgColumns,			// [OUT] Array of column numbers
		ECOLS_IN_LIST	eColsInList = ALL_COLS_IN_LIST,// [IN] Indicates which columns are included in list
		BOOL			fAddParams=FALSE,	// [IN]  TRUE if parameterized search criteria 
											//			   is added for each searchable column
		BOOL			fAddData=FALSE,		// [IN]  TRUE if data search criteria is
											//			   added for each searchable column
		WCHAR ***		prgColumnNames=NULL,// [OUT] Column names, if null are not returned		
		EVALUE			eValue=PRIMARY,		// [IN]  Type of makedata (Default = PRIMARY)
		DBCOUNTITEM		ulRowNumber = 1,	// [IN]  Row number to use
		DBORDINAL		iOrdinal = 0		// [IN] Col number to use, default 0 (all)
	);

	// @cmember Returns the columns in the query in query order and the 
	// base table ordinal value it cooresponds to.
	// <nl>
	// Since there is at least 1 EQUERY that encapsulates 2 select
	// statements, there will be a need to check pXX1 and pXX2.
	// <nl>
	// Client is responsible for releasing memory.The actual strings in the array of
	// column names is NOT to be released. The owner of the strings is CTable,
	// and the CTable::DropTable() function will release that memory.
	BOOL CTable::GetQueryInfo
	(
		EQUERY			sqlStmt,				// [in] SQL statement
		DBORDINAL *		pcColumns1,				// [out] 1.Count of columns
		DB_LORDINAL**	prgColumns1,			// [out] 1.Array of Column Ordinals
		WCHAR ***		prgColumnNames1,		// [out] 1.Column names
		DBORDINAL *		pcColumns2,				// [out] 2.Count of columns
		DB_LORDINAL**	prgColumns2,			// [out] 2.Array of Column ordinals
		WCHAR ***		prgColumnNames2			// [out] 2.Column names
	);

	// @cmember Sets the member variables for a pre-existing table.
	HRESULT	SetExistingTable(WCHAR * pwszTableName = NULL); // [IN] Name of table, cannot be empty 
		
	// @cmember Sets table name if table name is currently NULL,
	// else returns EFAIL.Can return E_OUTOFMEMORY.
	HRESULT SetTableName(WCHAR * pTableName);

	// @cmember Retrieves a correctly quoted Name
	//  Even handles correctly quoting qualified names...
	HRESULT GetQuotedName(WCHAR* pwszName, WCHAR** ppwszQuoted, BOOL fFromCatalog = FALSE);
	HRESULT GetQualifiedName(WCHAR* pwszCatalogName, WCHAR* pwszSchemaName, WCHAR* pwszTableName, WCHAR** ppwszQualifiedName,
		BOOL fFromCatalog = FALSE);

	// @cmember Retrieves LiteralInfo for the requested LITERAL
	DBLITERALINFO* GetLiteralInfo(DBLITERAL dwliteral);

	// @cmember Sets view name if view name is currently NULL,
	// else returns EFAIL.Can return E_OUTOFMEMORY.
	HRESULT SetViewName(WCHAR * pViewName);

	// @cmember Sets which columns are used as search criteria 
	// in Select,Insert,Update,and Delete.
	HRESULT	SetColsUsed(CList <DBORDINAL,DBORDINAL>& rColNumList );	 // [IN] Sets ccol.m_fUseInSQL

	// @cmember Drops this table (which also drops index) from backend database.
	HRESULT	DropTable(BOOL fDropAlways = FALSE);

	// @cmember Drops this table (which also drops index) from backend database.
	HRESULT	DropTable(DBID*);

	// @cmember Drops the view on this table from backend database.
	HRESULT DropView(void);

	// @cmember Drops index on table.
	HRESULT DropIndex(void);

	// @cmember,mfunc Adds 1 to row count, should be called after insert is executed 
	// on this table outside of class.
	// @@parm [IN] Number of rows to add to count (Default = 1)
	 void AddRow(DBCOUNTITEM ulRow=1){m_ulRows += ulRow; m_ulNextRow += ulRow;};

	// @cmember,mfunc Removes 1 from row count, should be called after delete 
	// is executed on this table outside of class.
	// @@parm [IN] Number of rows to substract from count (Default = 1)
	 void SubtractRow(DBCOUNTITEM ulRow=1){if(m_ulRows>0) m_ulRows -= ulRow; if(m_ulNextRow>0) m_ulNextRow -= ulRow;};

	//Add a Column to the list
	HRESULT AddColumn(CCol& rCol);
	
	//Remove a Column from the table
	HRESULT DropColumn(CCol& rCol);

	//Remove a Column from the table; the column is given by its ordinal position
	HRESULT	DropColumn(DBORDINAL nOrdinalPos);

	// @cmember Turn m_ColList.fUseInSQL to TRUE/FALSE
	// [IN] Sets(TRUE) or clears(FALSE) ccol.m_fUseInSQL (Default=FALSE).<nl>
	// TRUE means use every column in the where clause.<nl>
	// FALSE means do not use any columns in where clause.<nl>
	HRESULT AllColumnsForUse(
		BOOL fValue=FALSE		
	);

	// @cmember Number of rows in base table. This function executes a "select * from" and
	// then counts all the rows on the table.
	// Zero is returned if there was an error.
	// Counts the rows in the table by seeing how many GetRows it
	// goes thru. Yes, this is expensive for large databases. If table name
	// is not set, return E_FAIL. Alloc (pwszSQLText).
	DBCOUNTITEM CountRowsOnTable(IRowset *pIRowset=NULL);	  
		
	// @cmember Number of rows in CTable object. Returns m_ulRows.
	 DBCOUNTITEM GetRowsOnCTable(void){return m_ulRows;};

	// @cmember Number of columns in CTable.
	// Zero is returned if there was an error.
	DBORDINAL CountColumnsOnTable(void);	   
		
	// @cmember,mfunc Returns TableName, client should not alter pointer.
	 WCHAR * GetTableName(void){return m_TableID.uName.pwszName;};

	// @cmember,mfunc Returns ViewName, client should not alter pointer.
	 WCHAR * GetViewName(void){return m_pwszViewName;};	
		
	// @cmember,mfunc Returns TableID
	 DBID GetTableID(void){return m_TableID;};	

	// @cmember,mfunc Returns the reference of TableID
	 DBID& GetTableIDRef(void){return m_TableID;};	

	// @cmember,mfunc Sets TableID
	void SetTableID(DBID d);

	// @cmember,mfunc Returns m_fHasAuto
	 BOOL GetHasAuto(void){
		return m_fHasAuto;}	

	// @cmember,mfunc Sets m_fHasAuto
	 void SetHasAuto(BOOL b){m_fHasAuto = b;}

	// @cmember,mfunc Returns m_fHasAuto
	 BOOL GetHasUnique(void){
		return m_fHasUnique;}	

	// @cmember,mfunc Sets m_fHasAuto
	 void SetHasUnique(BOOL b){m_fHasUnique = b;}

	// @cmember,mfunc Returns m_fHasAuto
	 BOOL GetHasCLSID(void){
		return m_fHasCLSID;}	

	// @cmember,mfunc Sets m_fHasAuto
	 void SetHasCLSID(BOOL b){m_fHasCLSID = b;}

	// @cmember,mfunc Returns m_fHasDefault
	 BOOL GetHasDefault(void){
		return m_fHasDefault;}	

	// @cmember,mfunc Sets m_fHasDeffault
	 void SetHasDefault(BOOL b){m_fHasDefault = b;}

	// @cmember,mfunc Returns IndexName, client should not alter pointer.
	 WCHAR * GetIndexName(void){return m_pwszIndexName;}
	
	// @cmember,mfunc Returns Module Name, client should not alter pointer.
	 WCHAR * GetModuleName(void);

	// @cmember,mfunc Returns next row number for insert statement.
	 DBCOUNTITEM GetNextRowNumber(void){return m_ulNextRow;}

	// @cmember Flag telling if Commands are supported on the CTable object.
	 BOOL GetCommandSupOnCTable(void) { return m_pIDBCreateCommand!=NULL;	}

	// @cmember,mfunc Sets I4 for SQL support, m_lSQLSupport.
	// @@parmopt [IN] SQL Support (Default = 0)
	 void SetSQLSupport(LONG_PTR lSQLSupport=0)
				{m_lSQLSupport=lSQLSupport;}
	
	// @cmember,mfunc Returns I4 for SQL support, m_lSQLSupport.
	 LONG_PTR GetSQLSupport(void){return m_lSQLSupport;}

	// @cmember Flag telling if the Provider is ReadOnly.
	 BOOL GetIsProviderReadOnly(void){return m_fProviderReadOnly;}

	// @cmember Gets the columns to be used as search criteria in 
	// Select,Insert,Update,and Delete. Information on how to 
	// traverse the returned structure can be found in the MFC
	// reference on CList.
	HRESULT GetColsUsed(
		CList <DBORDINAL,DBORDINAL>& rColNumList	// [OUT] Gets ccol.m_fUseInSQLs 
	);

	HRESULT SetExistingCols(
	CList<CCol,CCol&> &InColList 
	);

	// @cmember delete without using commands
	HRESULT DeleteRows(			
		DBCOUNTITEM	ulRowNumber=ALLROWS // @parm [IN]  row # to pass  (Default = ALLROWS)	
	);

	// @cmember Sets m_pUnkOuter
	 IUnknown *SetUnkOuter(IUnknown *pUnkOuter = NULL) {
		return m_pUnkOuter = pUnkOuter; }

	// @cmember Gets m_pUnkOuter
	 IUnknown *GetUnkOuter(void) {
		return m_pUnkOuter; }

	// @cmember Sets the reference to the required rowset reference (for ITableDefinition)
	 IID	*SetRIID(IID* riid = (struct _GUID*)&IID_IRowset) {
		return m_riid = riid; }

	// @cmember Gets the reference to the required rowset reference (for ITableDefinition)
	 IID	*GetRIID(void) {
		return m_riid; }

	// @cmember Sets the property sets
	DBPROPSET *SetPropertySets(
		DBPROPSET *rgPropertySets = NULL, 
		ULONG cPropSets = 0
	);
	
	// @cmember Gets the property sets to be set or set by ITableDefinition::CreateTable
	 DBPROPSET *GetPropertySets(void) {
		return m_rgPropertySets; }

	// @cmember Sets the number of property sets for ITableDefinition::CreateTable
	 ULONG SetNoOfPropertySets(ULONG cPropertySets = 0) {
		return m_cPropertySets = cPropertySets; }

	// @cmember Gets the number of property sets 
	 ULONG GetNoOfPropertySets(void) {
		return m_cPropertySets; }

	// @cmember Sets the column description array
	DBCOLUMNDESC *SetColumnDesc(DBCOLUMNDESC *rgColumnDesc = NULL);
	
	// @cmember Sets the column description array
	DBCOLUMNDESC *SetColumnDesc(DBCOLUMNDESC *rgColumnDesc, DBORDINAL cColumnDesc);
	
	// @cmember Gets the property sets to be set or set by ITableDefinition::CreateTable
	 DBCOLUMNDESC *GetColumnDesc(void) {
		return m_rgColumnDesc; }

	// @cmember Sets the number of column descriptors for ITableDefinition::CreateTable
	 DBORDINAL SetNoOfColumnDesc(DBORDINAL cColumnDesc = 0) {
		return m_cColumnDesc = cColumnDesc; }

	// @cmember Use &m_TableID as input TableID in ITableDefinition::CreateTable
	 BOOL SetInputTableID(void) {
		return m_fInputTableID = TRUE;}

	// @cmember Use NULL as input TableID in ITableDefinition::CreateTable
	 BOOL ResetInputTableID(void) {
		return m_fInputTableID = FALSE;}

	// @cmember Get m_fInputTableID
	 BOOL GetInputTableID(void) {
		return m_fInputTableID;}

	// @cmember SetBuildColumnDesc
	 BOOL SetBuildColumnDesc(BOOL v) {
		return m_fBuildColumnDesc = v;}

	// @cmember GetBuildColumnDesc
	 BOOL GetBuildColumnDesc(void) {
		return m_fBuildColumnDesc; }


	// @cmember Sets pointer to the return table DBID (in ITableDefinition::CreateTable)
	DBID	**SetDBID(DBID **ppTableID = NULL);

	// @cmember Gets pointer to the return table DBID created by ITableDefinition::CreateTable
	DBID **GetDBID(void);

	// @cmember Sets pointer to the rowset interface to be created by ITableDefinition::CreateTable
	IUnknown **SetRowset(IUnknown **ppRowset = NULL);

	// @cmember Gets the pointer to the rowset interface created by ITableDefinition::CreateTable
	IUnknown **GetRowset(void);

	// @cmember Gets the column properties that could be read
	ULONG	GetColProps(void){
		return m_fColProps; }

	// @cmember Duplicate the column list, it's user responsability to free it
	CList <CCol, CCol&>	&DuplicateColList(CList <CCol, CCol&> &ColList);

	// @cmember Set the column list
	CList <CCol, CCol&>	&SetColList(CList <CCol, CCol&> &ColList);

	// @cmember Creates initial list of types,initializes m_ColList with columns of 
	// specified types.
	HRESULT CreateColInfo(
		CList<WCHAR *,WCHAR *>& rProviderTypesNameList,	// [OUT] CList of WCHAR * of ProviderTypeNames
		CList<DBTYPE,DBTYPE>& rProviderTypesList,		// [OUT] CList of DBTYPE of ProviderTypes
		EDATATYPES eDataTypes=ALLTYPES,					// [IN]  Data types (Default = ALLTYPES)	
		BOOL fFirstUpdateable = FALSE						// [IN] TRUE means first column will not be autoinc (Default=FALSE)
	);

	// @cmember Creates initial list of types,initializes m_ColList with columns of 
	// specified types.
	HRESULT CreateTypeColInfo(
		CList<WCHAR *,WCHAR *>& rProviderTypesNameList,	// [OUT] CList of WCHAR * of ProviderTypeNames
		CList<DBTYPE,DBTYPE>& rProviderTypesList,		// [OUT] CList of DBTYPE of ProviderTypes
		EDATATYPES eDataTypes=ALLTYPES,					// [IN]  Data types (Default = ALLTYPES)
		ULONG *pulAutoIncPrec=NULL						// [OUT] Precision of largest Auto Inc column (optional)

	);

	// @cmember Checks columns for Updatability. Used in the createtable functions.
	HRESULT MayWrite(
		BOOL * fMayWrite=NULL // [OUT] Is Column Writeable (Default=NULL).
	);

	// @cmember Returns first numeric (4 byte or larger) column <nl>
	HRESULT GetFirstNumericCol(CCol * pCCol);
	
	// @cmember returns list of not nullable columns
	HRESULT CTable::GetNullableCols	(WCHAR **prgColName);

	// @cmember Builds a variant which can represent the default value of a type
	BOOL	BuildDefaultValue(CCol& col, DBCOUNTITEM cRow, VARIANT *vDefault = NULL);
	
	// @cmember Sets the default value of a column
	BOOL	SetDefaultValue(CCol& col, DBCOUNTITEM cRow);
	
	// @cmember Sets the has default value of a column
	BOOL	SetHasDefaultValue(CCol& col, BOOL fHasDefaultValue);

	// @cmember Gets a column that satisfies several criteria
	BOOL	GetColWithAttr(ULONG cCond, ULONG *rgCond, DBORDINAL *pcSelectedColumn);
	BOOL	GetColWithAttr(ULONG ulCond, DBORDINAL *pcSelectedColumn)
			{ return GetColWithAttr(1, &ulCond, pcSelectedColumn); }

	// @cmember get the order by column
	HRESULT GetOrderByCol(
				CCol * pCCol	// @parm [in/out] Pointer to CCol object to copy 								
	);

	// @access Private
	private:	 
	
	// @cmember All functionality common to 3 CreateTable functions. <nl>
	// Called from one of the overloaded CreateTable functions.Passing zero
	// for ulIndex means do not but an Index on this table. eValue means
	// to create table with eValue kind of data. <nl>
	//
	// 1) Get Table Name <nl>
	// 2) Get Datatypes from Datasource <nl>
	// 3) Determine if we'll use command with SQL or ITableDefinition <nl>
	// 4) If using command, build sql/execute string for creating table <nl>
	// 5) Create Table <nl>
	// 4) Create Index, if requested <nl>
	// 5) Fill table with rows, if requested <nl>
	//
	// create table SQL statement looks like:
	// "create table <TableName> (col1 type,col2 type)"
	HRESULT QCreateTable(
		DBCOUNTITEM	ulRowCount,	// [IN] # of Rows to insert into table, 1 based 
		DBORDINAL	ulIndex,	// [IN] Column Number of index, 1 based 
		EVALUE 		eValue		// [IN] Type of data to insert
	);
	
	// @cmember Returns System Time. Used to create table name.
	// Client must IMalloc->Free returned string.
	WCHAR * GetTime(void);


	public:

	// @cmember Checks if Table currently exists based on a tablename search.
	// Make sure table is in Data Source, E_FAIL if table name is empty.
	// If table is found set fExists to true. If function runs correctly
	// but doesn't find the table name, function will return NOERROR, but fExists
	// will be FALSE. 
	HRESULT DoesTableExist(
		WCHAR * 	pwszTableName=NULL,	//  [IN]  Table name to check for (Default=NULL)
		BOOL *		fExists=NULL		//  [OUT] TRUE if table is found (Default=NULL)
	);
	
	// @cmember Checks if Table currently exists based on a tablename search.
	// Make sure table is in Data Source, E_FAIL if table name is empty.
	// If table is found set fExists to true. If function runs correctly
	// but doesn't find the table name, function will return NOERROR, but fExists
	// will be FALSE. 
	HRESULT DoesTableExist(
		DBID * 		pTableID=NULL,		//  [IN]  Pointer to Table DBID to check for (Default=NULL)
		BOOL *		fExists=NULL		//  [OUT] TRUE if table is found (Default=NULL)
	);

	public:
	// @cmember Checks if Index currently exists based on indexname search.
	// If this index is on this table return true and fill in
	// strIndexName and udwIndex, set fExists to true. If function runs correctly
	// but doesn't find the table name, function will return NOERROR, but fExists
	// will be FALSE. If strIndexName is empty, returns E_FAIL.	Assumes table
	// will have only 1 index.
	HRESULT DoesIndexExist(
		BOOL *		fExists=NULL		// [OUT] TRUE if index exists (Default=NULL)
	);

	// @cmember Used in Select to get literal prefix, makedata, and literal suffix
	// Client must IMalloc->Free((*ppwszData)).
	HRESULT GetLiteralAndValue(
		CCol &		col,				// [IN]  Col to grab prefix and suffix from
		WCHAR ** 	ppwszData=NULL,		// [OUT] Prefix, data, suffix like 'zbc' or #222 (Default=NULL)
		DBCOUNTITEM	ulRow=1,			// [IN]  Row number to pass to MakeData (Default=1)
		DBORDINAL	ulColNum=1,			// [IN]  Column number to pass to MakeData (Default=1)
		EVALUE 		eValue=PRIMARY,		// [IN]  PRIMARY or SECONDARY data (Default=PRIMARY)
		BOOL		fColData=FALSE		// [IN]  Whether to use col to make the data (Default = FALSE)
	);

	// @cmember FormatVariantLiteral	
	// Formats a variant literal using ODBC canonical convert functions
	HRESULT CTable::FormatVariantLiteral
	(
		DBTYPE		wVariantType,		// [IN] variant sub type
		WCHAR *		pwszData,			// [IN] input data
		WCHAR ** 	ppwszData			// [OUT] formatted data
	);

	// @cmember Generates Table Name
    // Looks like "MODULENAME_DATE_RANDOMNUMBER" example "persist_950101_9563".
	HRESULT MakeTableName(WCHAR* pwszTableName);

	// @cmember Fill m_ColList with information about current table
	HRESULT SetTableColumnInfo(
		WCHAR * pwszTableName = NULL,	// [IN] Table Name
		IUnknown *pIRowset=NULL			// [IN] Rowset from command
	);	

	// @cmember Fill m_ColList with information about current table
	HRESULT GetTableColumnInfo(
		DBID *		pTableID,			// [IN] Table ID
		IUnknown *pIRowset=NULL			// [IN] Rowset from command
	);	

	// @cmember Builds m_ColList from information in rgColumnDesc
	BOOL ColumnDesc2ColList(
		DBCOLUMNDESC	*rgColumnDesc,		// [IN] An array of ColumnDesc build from m_ColList
		DBORDINAL		cColumnDesc			// [IN] the number of elements in the array
	);	

	// @cmember Fill m_ColList with information about current table
	BOOL ColList2ColumnDesc(
		DBCOLUMNDESC	**rgColumnDesc,		// [OUT] An array of ColumnDesc build from m_ColList
		DBORDINAL		*cColumnDesc = NULL	// [OUT] the number of elements in the array
	);	

	// @cmember Puts the elements of CCol in m_ColList.
	HRESULT GetFromColumnsRowset(
		IColumnsRowset * pIColumnsRowset,	// [IN]	 IColumnsRowset pointer
		DBORDINAL *		 cColsFound=NULL	// [OUT] Total number of columns found (Default=NULL)
	);

	// @cmember Updates elements in m_ColList based on values read from column schema rowset
	HRESULT AddInfoFromColumnsSchemaRowset(
		IUnknown		*pIUnknown,				// [IN] session interface
		WCHAR			*pwszTableName = NULL,	// [IN]	table name (if null go for current table)
		DBCOUNTITEM		*cColsFound = NULL		// [OUT] Total number of columns found (Default=NULL)
	);

	private:
	// @cmember Puts the elements of CCol in m_ColList.
	HRESULT SetFromIDBSCHEMATypes(
		DBORDINAL *		cColsFound=NULL	// [OUT] Total number of columns found (Default=NULL)
	);

	// @cmember Puts the elements of CCol in m_ColList.
	HRESULT SetFromIDBSCHEMAColumns(
		DBORDINAL *		cColsFound=NULL	// [OUT] Total number of columns found (Default=NULL)
	);

	// @cmember Setups up cache for LiteralInfo
	HRESULT SetupLiteralInfo();

	// @cmember Sets the corresponding member function.
	HRESULT SetModuleName(
		WCHAR * pwszModuleName=NULL // [IN] Test Case Module Name (Default=NULL)
	);

	// @cmember Sets the column description array
	BOOL IsCompatibleType(
		DBCOUNTITEM		cBindings,
		DBBINDING*		rgBindings,
		void*			pData,
		CCol &			rCol			// @parm [IN] Element from the CCol List
	);

	// @cmember Creates DBPARAMBINDINFO and rgParamOrdinal array given desired 
	// bindings, column ordinals.  User must free pParamOrdinals, pParamBindInfo.
	HRESULT GetDBPARAMBINDINFO(
		DBCOUNTITEM		cBindings,
		DBBINDING*		rgBindings,
		DB_LORDINAL	*	rgColOrds,
		DB_UPARAMS **	ppParamOrdinals,
		DBPARAMBINDINFO ** ppParamBindInfo
	);

};																			
#endif // _CTable_

